完成Metis M1开发计划,开发者可基于Metis构建常规DAPP
Metis GitHub:https://github.com/patractlabs/metis Metis文件:https://patractlabs.github.io/metis/overview.html
ERC20及其扩展组件
ERC721及其扩展组件
ERC777及其扩展组件
ERC1155及其扩展组件
Ownable
AccessControl
TimelockController
PullPayment
support(ERC165)
ReentrancyGuard
Pauseable
注意:由于 Metis 的测试用例量很大,我们应该为每个合约单独运行测试。详细命令请参考 Metis 示例自述文件(https://github.com/patractlabs/metis/blob/master/example/README.md)。
1
Metis 的未来开发计划
2
2.1 实现基本组件宏
contract
: 按照 Metis 的合约标准定义合约。
import
: 生成代码来实现组件。
metis
: 定义 Metis 组件。
stub
: 在 Metis 中实现存根。
reentrancy_guard
:reentrancy_guard
组件的辅助宏。
supports
: ERC165 的辅助宏支持 API。
hash
: 在编译期间计算字符串的哈希值。
selector_id
: 计算消息的selector_id
.
注意:上面列出的当前可用的宏是最小的实现,将在 [M2] 里程碑中进行扩展和强化,请参阅使用组件(https://patractlabs.github.io/metis/#/./zh-cn/use-component?id=use-component)。
2.2 组件
Metis——MCCI 架构
M
: 数据模型。大多数合约读取和写入合约环境状态。这些状态映射到特定的数据模型。每个模型仅与一个组件相关联。C
: 组件。成分。组件是一个可重用的、独立的实现单元,它封装了数据和方法,但与其他组件保持正交性。C
: 控制器。控制器协调各组件并实现合约接口。I
:接口。合约的用户接口。该接口定义了合约的交互,并进一步定义了 metadata.。contructor
message
event
继承 VS 组合
/// The `EventEmit` impl the event emit api for ownable component.
pub trait EventEmit<E: Env>: EnvAccess<E> {
/// Emit OwnershipTransferred event
fn emit_event_ownership_transferred(
&mut self,
previous_owner: Option<E::AccountId>,
new_owner: Option<E::AccountId>,
);
}
/// The `Impl` define ownable component impl funcs
pub trait Impl<E: Env>: Storage<E, Data<E>> + EventEmit<E> {
/// init Initializes the contract setting the deployer as the initial owner.
fn init(&mut self) {
// logic
}
/// Message impl
fn one_message_impl(&mut self) -> Result<()> {
// msg impl which will call by ```xxx::Impl::one_message_impl(self)```
// use the hook
self.hook(xxx)?
Ok(())
}
/// Message for Query impl
fn one_query_impl(& self, param_acc: &E::AccountId) -> Data {
Data::default()
}
/// API for other message
fn check_xxx(&self, owner: &E::AccountId) {
}
// Hook which need impl by contract
fn hook(&mut self, params: &E::Balance) -> Result<()>;
}
// a default impl, each contract which impl storage and event emitter can be component
impl<E: Env, T: Storage<E, Data<E>> + EventEmit<E>> Impl<E> for T {}
#![cfg_attr(not(feature = "std"), no_std)]
#[metis_lang::contract] // use `metis_lang::contract`
pub mod contract {
// use the component: xxx1 and xxx2
use metis_component_xxx1 as xxx1;
use metis_component_xxx2 as xxx2;
// use `import` and `metis` marco
use metis_lang::{
import,
metis,
};
#[ink(storage)]
#[import(xxx1, xxx2)] // import the component
pub struct Contract {
// add data to storage, which use Contract as Env to Data
xxx1: xxx1::Data<Contract>,
xxx2: xxx2::Data<Contract>,
}
/// add event for component
/// in emit it will be emit_event_ownership_transferred
#[ink(event)]
#[metis(xxx1)] // event for xxx1
pub struct OwnershipTransferred {
/// previous owner account id
#[ink(topic)]
previous_owner: Option<AccountId>,
/// new owner account id
#[ink(topic)]
new_owner: Option<AccountId>,
}
/// Event emitted when payee withdraw
#[ink(event)]
#[metis(xxx2)] // event for xxx1
pub struct OtherEvent {
#[ink(topic)]
pub payee: AccountId,
pub amount: Balance,
}
impl xxx1::Impl<Contract> for Contract {
fn hook(
&mut self,
params: &E::Balance
) -> Result<()> {
// some logic
Ok(())
}
}
// impl
impl Contract {
#[ink(constructor)]
pub fn new() -> Self {
// impl for default
let mut instance = Self {
xxx1: xxx1::Data::new(),
xxx2: xxx2::Data::new(),
};
// init call
xxx1::Impl::init(&mut instance);
xxx2::Impl::init(&mut instance);
// return instance
instance
}
/// commits for one_message_impl
#[ink(message)]
pub fn one_message_impl(&mut self) -> Result<()> {
// some other check
xxx2::Impl::do_some_check(self);
xxx1::Impl::one_message_impl(self)
}
/// commits for one_query_impl
#[ink(message, payable)]
pub fn one_query_impl(&self, payee: AccountId) {
xxx1::Impl::one_query_impl(self, payee)
}
/// commits for other_message_impl
#[ink(message)]
pub fn other_message_impl(&mut self, payee: AccountId) {
xxx1::Impl::check_xxx(self)
// other logic
}
}
#[cfg(test)]
mod tests {
// test for contract
}
}
Hook 和 Impl
hook
: // Hook which need impl by contract
fn hook(&mut self, params: &E::Balance) -> Result<()>;
hook
有一个默认实现:
/// @dev Hook that is called before any token transfer. This includes
/// calls to {send}, {transfer}, {operatorSend}, minting and burning.
///
/// Calling conditions:
///
/// - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
/// will be to transferred to `to`.
/// - when `from` is zero, `amount` tokens will be minted for `to`.
/// - when `to` is zero, `amount` of ``from``'s tokens will be burned.
/// - `from` and `to` are never both zero.
///
/// To learn more about hooks,
/// head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
fn _before_token_transfer(
&mut self,
_operator: &E::AccountId,
_from: &Option<&E::AccountId>,
_to: &Option<&E::AccountId>,
_amount: &E::Balance,
) -> Result<()> {
Ok(())
}
该hook
将被组件函数自动调用。用户可以定义自己的hook
。 这里有一个例子,是在 Pausable ERC20 组件中:
fn before_token_transfer(
&mut self,
_from: &E::AccountId,
_to: &E::AccountId,
_amount: E::Balance,
) -> Result<()> {
metis_pausable::Impl::<E>::ensure_not_paused(self);
Ok(())
}
Pausable ERC20 组件通过实现hook
扩展了本地 ERC20 组件。
Metis 合约组件
在 Metis 的未来版本中,我们将首先完整实现 openZeppelin-contracts 组件供开发者使用。这些组件包括:
Token:ERC20、ERC721、ERC777、ERC1155 以及这些 Token 合约的扩展。
访问权限:Ownable、AccessControl、TimelockController。
安全性:PullPayment、ReentrancyGuard、Pausable。
Metis 将实现一套通用组件,类似于 OpenZeppelin-Contracts库。确保所有库的代码都经过全面测试和审计,这些组件将尽可能地与 OpenZeppelin-Contracts 保持一致,通过吸收从 Solidity 生态中学到的经验来平滑开发者的学习曲线:
ERC20(https://patractlabs.github.io/metis/tokens/erc20.html)
ERC721(https://patractlabs.github.io/metis/tokens/erc721.html)
ERC777(https://patractlabs.github.io/metis/tokens/erc777.html)
ERC1155(https://patractlabs.github.io/metis/tokens/erc1155.html)
Ownable(https://patractlabs.github.io/metis/access-control/ownable.html)
AccessControl(https://patractlabs.github.io/metis/access-control/access-control.html)
Access Control Enumerable(https://patractlabs.github.io/metis/access-control/access-control-enumerable.html#access-control-enumerable)
TimelockController(https://patractlabs.github.io/metis/governance/timelock-controller.html)
Escrow(PullPayment)(https://patractlabs.github.io/metis/utilities/escrow.html)
Support(ERC165)(https://patractlabs.github.io/metis/tools/erc165.html)
ReentrancyGuard(https://patractlabs.github.io/metis/security/reentrancy-guard.html)
Pausable(https://patractlabs.github.io/metis/security/pausable.html)
有关每个组件的详细信息,请参阅文档。
2.3 示例和测试
每个组件都附带了 ink! 链下测试环境和 Redspot 的默认实现示例和测试用例。
About Patract
Patract为波卡Wasm合约生态的平行链和DApp开发提供解决方案。我们帮助社区平行链设计和开发链上合约模块和Runtime支持,并且为DApp开发者提供覆盖开发、测试、调试、部署、监控、数据提供和前端开发等阶段的全栈工具和服务支持。
How to join Patract
1.对于合约开发者,可以访问官网(https://patract.io),熟悉测试链和工具套件。欢迎加入官方开发群:
Element(https://app.element.io/#/room/#PatractLabsDev:matrix.org)
Discord(https://discord.gg/wJ8TnTfjcq)
2.对于将要集成Wasm合约功能的平行链项目方,或者使用Wasm合约开发的DApp项目方,欢迎加入Patract 开放平台:https://open.patract.io
3.对于用户,欢迎加入:
Telegram(https://t.me/patract)
Twitter(https://twitter.com/PatractLabs)
4.对于求职者,我们在招聘区块链开发工程师、前端/全栈开发工程师、产品经理等岗位,可以联系 sean@patract.io
扫码加入Patract微信开发群
往期精彩: // Wasm合约测试网Jupiter已发布平行链版本 // PatraShare#8回顾|合约模型和合约语言(框架) // 聚焦去中心计算:在可信平台,如何保证执行一致性的问题?